package com.xxxx.paipaicars.utils;

import com.xxxx.paipaicars.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 定义一个任意类型的转换
 * <p>
 * bean 类型转换
 * ①Apache 工具类
 * ②Spring 工具类
 * ③Cglib 库
 * <p>
 * Created by frank on 2022/11/15.
 */
@SuppressWarnings("all")
@Slf4j
public class BeanCopyUtil {

    /**
     * 单个对象拷贝
     *
     * @param source 源对象
     * @param clazz  目标对象字节码
     * @param <T>    目标对象泛型
     * @return 目标对象
     */
    public static <T> T copyProperties(Object source, Class<T> clazz) {
        try {
            // 创建一个目标类型的对象
            T result = clazz.newInstance();
            // 将源对象拷贝到目标对象中
            BeanUtils.copyProperties(source, result);
            // 返回目标对象
            return result;
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        throw new BusinessException("对象拷贝异常");
    }

    /**
     * 单个对象拷贝(忽略字段)
     *
     * @param source           源对象
     * @param clazz            目标对象字节码
     * @param <T>              目标对象泛型
     * @param ignoreProperties 拷贝过程中忽略的字段
     * @return 目标对象
     */
    public static <T> T copyPropertiesIgnoreProperties(Object source, Class<T> clazz, String[] ignoreProperties) {
        try {
            // 创建一个目标类型的对象
            T result = clazz.newInstance();
            // 将源对象拷贝到目标对象中
            BeanUtils.copyProperties(source, result, ignoreProperties);
            // 返回目标对象
            return result;
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        throw new BusinessException("对象拷贝异常");
    }

    /**
     * list对象拷贝(V3)
     * 此方法只关心遍历(迭代)的动作,并不关心拷贝过程
     *
     * @param sources 源对象集合
     * @param clazz   目标对象字节码
     * @param <S>     源对象泛型
     * @param <T>     目标对象泛型
     * @return 新的集合袋子
     */
    public static <S, T> List<T> copyPropertiesList(List<S> sources, Class<T> clazz) {
        return sources.stream()
                .map(item -> BeanCopyUtil.copyProperties(item, clazz))// 映射过程
                .collect(Collectors.toList());// 流式收集
    }

    /**
     * list对象拷贝(V3)
     * 此方法只关心遍历(迭代)的动作,并不关心拷贝过程
     *
     * @param sources          源对象集合
     * @param clazz            目标对象字节码
     * @param <S>              源对象泛型
     * @param <T>              目标对象泛型
     * @param ignoreProperties 拷贝过程中忽略的字段
     * @return 新的集合袋子
     */
    public static <S, T> List<T> copyPropertiesListIgnoreProperties(List<S> sources, Class<T> clazz, String[] ignoreProperties) {
        return sources.stream()
                .map(item -> BeanCopyUtil.copyPropertiesIgnoreProperties(item, clazz, ignoreProperties))// 映射过程
                .collect(Collectors.toList());// 流式收集
    }

}
